#include <cassert>
#include <set>
#include <nice2d/components/country.h>
#include <nice2d/components/tilemappathfinder.h>
#include <nice2d/components/shortestpathfinder.h>
#include <nice2d/application.h>

class TileMapPathFinderData
{
public:
    TileMapPathFinderData()
    {
        finder = std::make_shared<ShortestPathFinder>();
    }

    void buildTileFlags()
    {
        countryManager = ADD_COMPONENT(Application::getInstance(), CountryManager);
        assert(countryManager);

        tileMap->accept(std::bind(&TileMapPathFinderData::visitTile, this, std::placeholders::_1,
                                  std::placeholders::_2, std::placeholders::_3));
    }

    void visitTile(int32_t x, int32_t y, std::shared_ptr<Tile> tile)
    {
        auto color = tile->getOwner();
        if (!countryManager->getCountry(startColor)->isAllied(color)) {
            auto list = tileMap->getAdjacentTileByTileIndex(x, y);
            std::for_each(list.begin(), list.end(), [&](const sf::Vector2i & index) {
                auto currentTile = tileMap->getTileByIndex(index);
                if (currentTile)
                    tileFlags.insert(GET_TILE_POSITION(x, y));
            });
        }
    }

    void buildGraph()
    {

    }

    ShortestPathFinderPointer finder;

    TileMapPointer tileMap;
    sf::Color startColor;
    std::shared_ptr<CountryManager> countryManager;

    std::set<uint32_t> tileFlags;
};

TileMapPathFinder::TileMapPathFinder(NodePointer object):
    Component(object),
    data(new TileMapPathFinderData)
{
    data->tileMap = std::dynamic_pointer_cast<TileMap>(object);
    assert(data->tileMap);
}

TileMapPathFinder::~TileMapPathFinder()
{
}

uint32_t TileMapPathFinder::search(uint32_t from, uint32_t to, bool zoc,
                                   std::vector<uint32_t> &list)
{
    list.clear();

    auto x = GET_TILE_X(from);
    auto y = GET_TILE_Y(from);
    auto tile = data->tileMap->getTileByIndex(x, y);

    if (!tile || tile->isWalkable() || tile->getOwner() == sf::Color::Transparent)
        return 0;

    data->startColor = tile->getOwner();

    x = GET_TILE_X(to);
    y = GET_TILE_Y(to);
    tile = data->tileMap->getTileByIndex(x, y);

    if (!tile || !tile->isWalkable())
        return 0;

    if (!zoc)
        data->buildTileFlags();

    data->buildGraph();
    return data->finder->search(from, to, list);
}

